{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "9f2a9777",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数据形状: (1000, 2)\n",
      "\n",
      "前5行数据:\n",
      "   病人编号                病人症状\n",
      "0     1             消化不良,便秘\n",
      "1     2               心悸,失眠\n",
      "2     3            腰疼,脱发,眼干\n",
      "3     4  腹胀,便秘,哮喘,胸闷气短,消化不良\n",
      "4     5        神经衰弱,失眠,月经不调\n",
      "\n",
      "============================================================\n",
      "数据预处理\n",
      "============================================================\n",
      "总病例数: 1000\n",
      "前3个病例的症状:\n",
      "  病例1: ['消化不良', '便秘']\n",
      "  病例2: ['心悸', '失眠']\n",
      "  病例3: ['腰疼', '脱发', '眼干']\n",
      "\n",
      "症状总数: 15\n",
      "最常见的10个症状:\n",
      "  月经不调: 484次 (48.4%)\n",
      "  心悸: 452次 (45.2%)\n",
      "  失眠: 393次 (39.3%)\n",
      "  消化不良: 344次 (34.4%)\n",
      "  眼干: 311次 (31.1%)\n",
      "  神经衰弱: 188次 (18.8%)\n",
      "  便秘: 184次 (18.4%)\n",
      "  腰疼: 160次 (16.0%)\n",
      "  脱发: 151次 (15.1%)\n",
      "  胸闷气短: 140次 (14.0%)\n",
      "\n",
      "============================================================\n",
      "关联规则分析 - mlxtend库\n",
      "============================================================\n",
      "转换后的数据形状: (1000, 15)\n",
      "前5行转换数据:\n",
      "          0      1      2      3      4\n",
      "便秘     True  False  False   True  False\n",
      "哮喘    False  False  False   True  False\n",
      "失眠    False   True  False  False   True\n",
      "心悸    False   True  False  False  False\n",
      "易怒    False  False  False  False  False\n",
      "月经不调  False  False  False  False   True\n",
      "消化不良   True  False  False   True  False\n",
      "眼干    False  False   True  False  False\n",
      "神经衰弱  False  False  False  False   True\n",
      "耳鸣耳聋  False  False  False  False  False\n",
      "胸闷气短  False  False  False   True  False\n",
      "脱发    False  False   True  False  False\n",
      "腰疼    False  False   True  False  False\n",
      "腹胀    False  False  False   True  False\n",
      "鼻炎    False  False  False  False  False\n",
      "\n",
      "挖掘频繁项集...\n",
      "\n",
      "支持度: 0.05\n",
      "  频繁项集数量: 46\n",
      "  项集长度分布:\n",
      "    长度1: 14个\n",
      "    长度2: 21个\n",
      "    长度3: 11个\n",
      "  多项目频繁项集数量: 32\n",
      "  生成关联规则时出错: \"frozenset({'便秘'})You are likely getting this error because the DataFrame is missing  antecedent and/or consequent  information. You can try using the  `support_only=True` option\"\n",
      "  使用备选方法生成关联规则...\n",
      "  备选方法也失败: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().\n",
      "\n",
      "支持度: 0.1\n",
      "  频繁项集数量: 26\n",
      "  项集长度分布:\n",
      "    长度1: 11个\n",
      "    长度2: 13个\n",
      "    长度3: 2个\n",
      "  多项目频繁项集数量: 15\n",
      "  生成关联规则时出错: \"frozenset({'便秘'})You are likely getting this error because the DataFrame is missing  antecedent and/or consequent  information. You can try using the  `support_only=True` option\"\n",
      "  使用备选方法生成关联规则...\n",
      "  备选方法也失败: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().\n",
      "\n",
      "支持度: 0.15\n",
      "  频繁项集数量: 17\n",
      "  项集长度分布:\n",
      "    长度1: 9个\n",
      "    长度2: 7个\n",
      "    长度3: 1个\n",
      "  多项目频繁项集数量: 8\n",
      "  生成关联规则时出错: \"frozenset({'便秘'})You are likely getting this error because the DataFrame is missing  antecedent and/or consequent  information. You can try using the  `support_only=True` option\"\n",
      "  使用备选方法生成关联规则...\n",
      "  备选方法也失败: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().\n",
      "\n",
      "============================================================\n",
      "关联规则分析 - apyori库（备选方案）\n",
      "============================================================\n",
      "使用apyori库进行关联规则分析...\n",
      "apyori发现的关联规则数量: 7\n",
      "\n",
      "前10条关联规则:\n",
      "  便秘 → 消化不良\n",
      "    支持度: 0.160, 置信度: 0.870, 提升度: 2.528\n",
      "  失眠 → 月经不调\n",
      "    支持度: 0.318, 置信度: 0.809, 提升度: 1.672\n",
      "  神经衰弱 → 消化不良\n",
      "    支持度: 0.164, 置信度: 0.872, 提升度: 2.536\n",
      "  脱发 → 眼干\n",
      "    支持度: 0.143, 置信度: 0.947, 提升度: 3.045\n",
      "  腰疼 → 眼干\n",
      "    支持度: 0.136, 置信度: 0.850, 提升度: 2.733\n",
      "  心悸, 失眠 → 月经不调\n",
      "    支持度: 0.167, 置信度: 0.766, 提升度: 1.583\n",
      "  神经衰弱, 心悸 → 消化不良\n",
      "    支持度: 0.100, 置信度: 0.926, 提升度: 2.692\n",
      "\n",
      "============================================================\n",
      "简单关联分析 - 手动实现\n",
      "============================================================\n",
      "执行简单关联分析...\n",
      "发现 13 个有意义的症状对\n",
      "\n",
      "前10个有意义的症状对:\n",
      "  1. 失眠 & 月经不调\n",
      "     支持度: 0.318\n",
      "     失眠 → 月经不调: 0.809\n",
      "     月经不调 → 失眠: 0.657\n",
      "  2. 心悸 & 月经不调\n",
      "     支持度: 0.249\n",
      "     心悸 → 月经不调: 0.551\n",
      "     月经不调 → 心悸: 0.514\n",
      "  3. 失眠 & 心悸\n",
      "     支持度: 0.218\n",
      "     失眠 → 心悸: 0.555\n",
      "     心悸 → 失眠: 0.482\n",
      "  4. 心悸 & 消化不良\n",
      "     支持度: 0.180\n",
      "     心悸 → 消化不良: 0.398\n",
      "     消化不良 → 心悸: 0.523\n",
      "  5. 月经不调 & 眼干\n",
      "     支持度: 0.170\n",
      "     月经不调 → 眼干: 0.351\n",
      "     眼干 → 月经不调: 0.547\n",
      "  6. 消化不良 & 神经衰弱\n",
      "     支持度: 0.164\n",
      "     消化不良 → 神经衰弱: 0.477\n",
      "     神经衰弱 → 消化不良: 0.872\n",
      "  7. 便秘 & 消化不良\n",
      "     支持度: 0.160\n",
      "     便秘 → 消化不良: 0.870\n",
      "     消化不良 → 便秘: 0.465\n",
      "  8. 眼干 & 脱发\n",
      "     支持度: 0.143\n",
      "     眼干 → 脱发: 0.460\n",
      "     脱发 → 眼干: 0.947\n",
      "  9. 眼干 & 腰疼\n",
      "     支持度: 0.136\n",
      "     眼干 → 腰疼: 0.437\n",
      "     腰疼 → 眼干: 0.850\n",
      "  10. 失眠 & 眼干\n",
      "     支持度: 0.116\n",
      "     失眠 → 眼干: 0.295\n",
      "     眼干 → 失眠: 0.373\n",
      "\n",
      "============================================================\n",
      "症状频率可视化\n",
      "============================================================\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAABKYAAAMWCAYAAADLc44dAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAACKB0lEQVR4nOzdd3RU1d7G8WeSmUwaKZQAgUCESNGgKFUEpRfhglipIoogCoKIIoooRSmCFEFQUVHhoqgUUYpUlV4ElCqhS4AQShokmfb+wZu5jAkh0YSTwPez1lmX0/b57eC5yOPe+5hcLpdLAAAAAAAAwHXmZXQBAAAAAAAAuDkRTAEAAAAAAMAQBFMAAAAAAAAwBMEUAAAAAAAADEEwBQAAAAAAAEMQTAEAAAAAAMAQBFMAAAAAAAAwBMEUAAAAAAAADEEwBQAAAAAAAEMQTAEAABQiZ86cueq52NjY61gJAADAv0cwBQAAriuXy6Xk5OQcb+np6dm2d/78eY/9pUuXqk+fPkpOTnYfO3ny5DXbyQ/jx4/X5s2bszw3YcIErV69Wi6XK8ftff7554qIiNDKlSsznTt//rwqVqyorl27/uN688rx48fVuHFjff3113nW5p9//qlnnnlGH3/8ca7v7d27twYNGpTp+K5duzRjxgz99ttveVEiAAD4BwimAADAdXXy5EkVKVJEJUuWVNmyZbPdihQpojFjxly1rRkzZuiOO+7wGCm0c+dOTZ061SPw6du3r+68804lJSVdtS273a59+/bleDt48GC2/UxNTdWgQYM0YcKETOdcLpdGjRqlp59+Wg6HI9t2rtS2bVsVL15c3bp1U2Jiose5adOmyWaz6cUXX8xxe/ll1KhRWr16tdatW5dnbVosFs2YMUMzZ87M9b3r1q3Tli1bMh3fsGGDnnnmGW3evFkul0t//PFHHlQKAAByw2x0AQAA4OYSEBAgSZo9e7YefPDBbK81mUzu67PSqlUrvf7663rkkUf0yy+/yGw2y2y+/K83Pj4+kqTdu3dr/vz5Gj58uIoUKXLVts6dO6eqVavmuB+VKlXS/v37r3p+3759cjgc6ty5c6Zz27dv15kzZ/TWW2+56/07u92ulJQU+fj4yMfHR97e3goNDdXkyZN15swZ+fr6uq9NSkrSe++9p2effVZ33323pMvhV2pqqhwOhwIDA3Pcr39r48aN+uijj1S8eHFNnz5dHTp0UL169XJ8/8GDB/Xrr79meS4oKEibNm3SJ598Im9vb0mX+2mz2ZSamqoePXrI399fDofDfV6SzGazLBZLpvYy/tmqUKGCZs2apaefflozZ85Up06dctNlAADwLxBMAQCA6yojMGjfvn2OrvfyyjzA+88//5TT6ZQkPf/88zp27JhiYmIkSfHx8ZKkAwcOyGw2a9CgQapQoYLat2+vffv2SZKKFSumEiVKeLRptVolSR9//LF69OiRbU1PPvmktm/fnu01u3fvlr+/v5o2bZrp3BdffCGTyaTQ0FD98MMPHudq1qypUqVKae3atWrUqNFV23/22WczHZs6daqmTp3qcez+++/XmjVrPI79+eefqlu3rubNm6eGDRtmaqdFixb66aefMh2fMGGC+vfvf9Wazp8/r86dOys8PFybN29WmzZt9Mgjj2jDhg0qX778Ve+70saNG9W9e3eFhoZm+r23WCwKCQnxmJbndDplt9t16dIlPfbYYzKZTGrSpIkeeeQRDRgwQNLlf4ZMJlOmZ2X8ngcEBKhr1676448/1LVrV5lMJnXs2DFH9QIAgH+HYAoAAFxXNptN0uVpeC1atMj22oiICNnt9kzH77nnHp07d87j2CeffOKxX61aNY/922+/3f3r4cOH64033vA4f+UImwyHDx/WJ598oiZNmmQKibIKOiSpe/fuHtPN/Pz83L/++eefdc8992j27NmyWCx65pln3OdcLpcuXryohQsXqm3btqpWrZpWrlyp0NBQWSyWq46supr09HQlJCS4R45liI2NVevWrTOtzXVlHZs3b1aHDh3UunVrj3M1a9a86vNSU1P1yCOP6NixY1q1apVKlSqluXPnqmbNmqpXr56WLl2a6fckw/79+7Vx40Z169bNHRZt3rxZUVFRuemyW8OGDfXyyy+rWrVqatas2VWvyxhFlfF7P3bsWCUlJSk8PPwfPRcAAOQewRQAALiu0tPTVblyZb377rt69913s722cuXKHsFOBn9/f3Xt2lUTJ07M9fPNZrPHNLjsxMbG6u2335a/v3+2o5f+Xlt4eLjHAuWbN29Wt27d5Ofnp2+++Ubx8fHatGmTateu7b7m4MGDioqKcgczxYoVU+PGjXX48OGrrmdVunRpj8Atw/Tp03Xu3Dm99tprHsc3bdqk9u3bZxnCZdi3b58uXLigbt26qWXLljnq84ULF/Too49q9erV+vLLL1WjRg3FxMSoePHi+umnn9S8eXM1aNBA06ZNy3Ik0pw5czR8+HD3KLIMBw4cUGJionx9fa9as81mU3p6ugICAlSlShVJ0ttvv62YmBh16dLFPZLuymv9/PyuOorqgw8+0MWLF2W323MdBgIAgNzjT1sAAHBdXLp0Sd7e3ipZsqR7Sl1OZKyVlJaWpuDgYHdbkrRjxw7dddddOWqnffv2mjdvnsf915KxMPmtt96a43q9vb1lsVjcIYkknTp1StLldaPefPNNNWnSxCOUyjgn/W96WYb//ve/GjJkiCpUqOARpBw9elRdu3bVp59+qu+//16LFy/W5MmT5ePjo8WLF+vo0aOZgqlXX33VPb3uaqPVNm7cKLPZnON1odauXatu3brpyJEjmjZtmjp37qzVq1ercePGmjx5svr27auVK1eqVatW6tSpk2bOnKnx48crOjra3cabb76p3bt366mnnvIYyfbmm29q3rx5slqt7tFNCQkJcrlcCgkJkXQ56ExPT1fz5s31/fffS7o8mm3mzJlaunSpx7piCxcu1KOPPpqpD/fcc0+mY7/++qvq16+fo58BAAD45wimAADAdfHoo4/qxx9//Mf3BwQEKDk5WdLlEUhBQUHu6XxTp051L/qdlRdeeME98urs2bOZwp+rSU1NlSSVKVMmx3VmtSZWhsWLF+vQoUOaM2eO0tLSPOq4WjCVsb97926PkV6RkZEe5z788ENNmzZN0uXpg1mNNJs+fboqV66cac2pK23YsEFFihRR69attWPHDlksFjVu3FgjRozwWBx+//79GjlypGbPnq2goCD98MMPatWqlSS5Rz1l1HDXXXfp999/V7du3dxT+u69916NHDlSDRs2lMlk0pdffqk5c+a41/7y8vLSf//730z1NWzYUKdOnbpmuOnv76+HHnrI41ijRo20efNm+fv7y9vbW7Nnz9bIkSM1YMAA97RKp9OpixcvqnLlytm2DwAA8gbBFAAAuC7effddjRw5Uq+//rosFovGjRsn6fKopCpVqmjWrFmqU6dOpvucTqfS0tLca1NJl7+iJl2eQiZJt912m+rWrXvVZwcFBbkDo4xRVzlx+vRpSZfXusoLDz/8sDp37qz4+HhFRkZq5cqVuu222yRdHvkjKdM0w4zw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SpLi4uKUnJysU6dOafr06Tp27JgkydfXV+PGjdOHH36owYMHKyAgQPPnz1exYsUkSWXKlHFP8YuOjtaUKVPUsGFD93MuXLig0NBQnT59Wmbz/7oRGRmpgwcPuvdbt26t/v37q02bNmratKl+//13ffLJJ7JareratWtuuw8AAAAAAIA8kutg6kqTJ0/WrFmzPI4dP37cY9/Hx8dj38vr8uxBk8kkb29vzZ49W8WKFdOLL76o9PR090inv+vcubP8/Pzc+xlrRmVn6NChOnbsmHr06KGDBw8qPj5e0dHRunjxokaMGKFLly55tAkAAAAAAIDr518tfv7CCy8oJibGY6tatWrOH+7lpYEDB6p06dI6d+6cvL29PUY/XWn27Nkez/ntt9+u2u6WLVvUqlUrff3111q4cKF69uypmjVr6uLFixo2bJhiYmLUtm1bNWzYULt27cp1vwEAAAAAAPDvGfpVPkl6/vnntW7dOjVr1kw1a9b81+25XC699957ioqK0qZNm1ShQgX17t1bhw4dUsOGDTVw4EBVrFhRderUUe3atVWlSpUs20lLS1NiYqLHBgAAAAAAgLzzr6byjR07VlOmTPE4duHChRzda7fb3b++//771bJlSzVp0uSq17dr1y7T4udZ2b59u4oVK6akpCQ1b95c9913n/vcHXfcoTvuuEMLFixQy5YtlZSUpA0bNqhBgwaZ2hk1apSGDRuWo74AAAAAAAAg9/5VMPXKK69kufh5dhwOhyTJ399f0dHRHudsNpsiIyO1c+fOTPctXLgwy8XP/+7uu+/W3XffrTVr1qhNmzZZrkV18OBBjRo1Sr6+vletc/DgwRowYIB7PzExUREREdn2DQAAAAAAADn3r4KpDE6nU8nJyUpOTlZ6err++OMPXbp0SQkJCXrggQd0/vx5NW3aVCdOnFDr1q116dIl7d692z0Cym63y263a8WKFZo8eXK2z7LZbEpOTtaJEyckST///LMSEhIUGBio5s2be1xbtmzZTMGZJP3nP/+5Zp+sVqusVmsOfwIAAAAAAADIrVwFU4cPH1afPn2UmJio/fv3KykpSePGjZPFYlFQUJCCg4N15MgRjR49WiEhIfLz81PLli3VsmVLLVy4UOnp6XI6nXrwwQe1ceNG90LnTqdTDzzwgJo1a6bixYtLkhYtWqQpU6YoKSlJBw8eVJs2bSRJvr6+CgoKUmBgoCTp6aeflp+fn+69995MwZTNZtOpU6ey7EtiYqLi4+PlcDhUvnz53P3UAAAAAAAA8K/lKpgKDw/XSy+9pGLFiikkJEShoaEqUqSITCaT+5rbb79dkyZNUtOmTd3HFi5cKEny8fGRJC1dutSj3dWrV2v79u0aP368HnzwQUlSjRo1NGTIEBUrVkzBwcEKDQ2Vv7+/+54zZ84oLCxMMTExHl/ymzt3rmbMmKH4+HidOnVKkydPlt1ul5eXl7y8vNy1du/eXUFBQapTp4769++fmx8DAAAAAAAA8kCugimr1arGjRtne01aWlqui7DZbPrtt9/UuXNn9e7dW9LlECw8PDzXz6lTp46KFCmiUqVKqVixYgoKClJQUJC8vP73AUKTyaRZs2ZluUYVAAAAAAAAro88WWPqSjExMbm+p3nz5pmm4V1L2bJls/wyX/ny5a85Ne9qX/QDAAAAAADA9eN17UsAAAAAAACAvEcwBQAAAAAAAEMQTAEAAAAAAMAQBFMAAAAAAAAwBMEUAAAAAAAADEEwBQAAAAAAAEMQTAEAAAAAAMAQBFMAAAAAAAAwBMEUAAAAAAAADEEwBQAAAAAAAEOYjS6gsKkdHqKQkBCjywAAAAAAACj0GDEFAAAAAAAAQxBMAQAAAAAAwBAEUwAAAAAAADAEwRQAAAAAAAAMQTAFAAAAAAAAQxBMAQAAAAAAwBAEUwAAAAAAADAEwRQAAAAAAAAMYTa6gMJmc+wFBSY7jS4DhUi9skWNLgEAAAAAgAKJEVMAAAAAAAAwBMEUAAAAAAAADEEwBQAAAAAAAEMQTAEAAAAAAMAQBFMAAAAAAAAwBMEUAAAAAAAADEEwBQAAAAAAAEMQTAEAAAAAAMAQBFMAAAAAAAAwRKEJplwulzp16qQLFy7k+t4TJ07I5XLlfVEAAAAAAAD4xwp8MDV06FBVqlRJjRo1UmxsrB588EE1bNjQvUVGRmr69Oke9yQlJenkyZOSpPj4eJUtW1b79++XJF26dEkjRoxQQkLCde8LAAAAAAAA/qfAB1MWiyXX18yfP1/t27eXJO3bt0/h4eGqUqWKJGnGjBlasGCB/P39875YAAAAAAAA5JjZ6AKuxWw2q0mTJmrRokWW57/66it5eXnma59//rmef/55SdKSJUtUokQJxcbGKjw8XEePHtXkyZNzFHgBAAAAAAAg/xT4EVM2m+2a19jtdo/9KVOm6NFHH9XOnTs1efJkValSRbVr11bTpk1VtWpVRUdH51e5AAAAAAAAyKECP2IqIiJCq1at0t69e696TVhYWKZ7pk2bphEjRmjkyJHq16+fnE6nli9frunTp6tv375q3769+vbtq7p16+Z3FwAAAAAAAJCFAh1M/fHHH/rss8/UuHFj97EdO3YoODhYt9xyi/vYW2+9pcaNG+vYsWMaNGiQVq9erTvuuEM//vij7rnnHnXp0kUDBw5UixYt1KJFC+3Zs0cjR47U119/fdVgKi0tTWlpae79xMTE/OsoAAAAAADATahAB1NOp1N//PGHfHx83McOHDigwMBAnThxwn1sz5498vHx0e23364GDRro5ZdfVr169dzrSC1evFj9+vWTJKWnpysmJkazZs3KtDbVlUaNGqVhw4blU88AAAAAAABQoIMpl8ulqKgoTZw40X1s/PjxioqKUrt27dzHGjZsKKfTKUkaNGiQ9u7dq4oVK+rAgQOy2Ww6f/684uLiJEkzZ87UjBkz1KJFC1mt1qs+e/DgwRowYIB7PzExUREREXncQwAAAAAAgJtXgQ6mihUrpvvvv18zZ870OHb+/HmPY08++aTHfR9++KEeeeQRWa1WLViwQBEREfr444/VunVrbdq0SVOmTMk2lJIkq9V6zWsAAAAAAADwzxXYYGrq1KmaM2eOzOZrl+hyudSkSRO98MIL6tChg1555RV5e3vr8OHDGjhwoGbMmKHp06fr9ddf18cff5ztFD4AAAAAAABcHwU2mOrZs6d69uwpSfrqq680ffp0LV68WMHBwZKkI0eO6Mknn9SaNWvkcrmUnp4ub29vSVJAQIA++eQTvfPOO3rppZfUokUL3XvvvWrTpo1q166tgQMH6oEHHlBQUJBh/QMAAAAAALjZFdihQ8eOHdNDDz2kjh07Ki0tTatXr3aHUtLlRcztdrskyWQyyWq1au/evWrWrJlKlSqlH374QYsWLdLgwYMlSYGBgVqxYoW6deumN954Q8WKFdNdd92lCxcuGNE9AAAAAACAm57J5XK5jC7ialwul0wmU67u+fzzz1W7dm1VrVo12+t27dqlc+fO6b777stRu4mJiQoODtay3YcVyEgr5EK9skWNLqHQcDqdiouLU1hYGFNugXzAOwbkL94xIP/x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",
      "text/plain": [
       "<Figure size 1200x800 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "============================================================\n",
      "关联规则分析总结\n",
      "============================================================\n",
      "\n",
      "============================================================\n",
      "业务建议\n",
      "============================================================\n",
      "\n",
      "💡 中医症状关联分析业务建议:\n",
      "\n",
      "1. **辨证参考**: 强关联的症状组合可为中医辨证提供参考\n",
      "2. **处方辅助**: 关联规则可辅助制定更精准的方剂\n",
      "3. **预防建议**: 识别症状关联有助于疾病预防和早期干预\n",
      "4. **临床验证**: 发现的关联需要在临床实践中进一步验证\n",
      "\n",
      "📊 分析方法建议:\n",
      "- 结合中医理论解释症状关联\n",
      "- 考虑患者体质、年龄等因素\n",
      "- 使用多种支持度阈值进行探索\n",
      "- 重点关注提升度 > 1.5 的强关联\n",
      "\n",
      "\n",
      "关联规则分析完成!\n"
     ]
    }
   ],
   "source": [
    "# 设置中文字体支持\n",
    "import matplotlib.pyplot as plt\n",
    "plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "\n",
    "# 1.读取数据\n",
    "import pandas as pd\n",
    "df = pd.read_excel(r\"D:\\贺之恒的python\\pppython\\python商业数据分析\\@Python大数据分析与机器学习商业案例实战\\第15章 关联规则分析-Apriori模型\\源代码汇总_PyCharm格式\\中医辨证.xlsx\")\n",
    "print(\"数据形状:\", df.shape)\n",
    "print(\"\\n前5行数据:\")\n",
    "print(df.head())\n",
    "\n",
    "# 2.数据预处理\n",
    "print(\"\\n\" + \"=\"*60)\n",
    "print(\"数据预处理\")\n",
    "print(\"=\"*60)\n",
    "\n",
    "# 转换为双重列表结构\n",
    "symptoms = []\n",
    "for i in df['病人症状'].tolist():\n",
    "    symptoms.append(i.split(','))\n",
    "\n",
    "print(f\"总病例数: {len(symptoms)}\")\n",
    "print(\"前3个病例的症状:\")\n",
    "for i in range(3):\n",
    "    print(f\"  病例{i+1}: {symptoms[i]}\")\n",
    "\n",
    "# 统计症状频率\n",
    "from collections import Counter\n",
    "all_symptoms = [symptom for case in symptoms for symptom in case]\n",
    "symptom_counts = Counter(all_symptoms)\n",
    "\n",
    "print(f\"\\n症状总数: {len(symptom_counts)}\")\n",
    "print(\"最常见的10个症状:\")\n",
    "for symptom, count in symptom_counts.most_common(10):\n",
    "    print(f\"  {symptom}: {count}次 ({count/len(symptoms)*100:.1f}%)\")\n",
    "\n",
    "# 3.使用mlxtend库进行关联规则分析（修复版本）\n",
    "print(\"\\n\" + \"=\"*60)\n",
    "print(\"关联规则分析 - mlxtend库\")\n",
    "print(\"=\"*60)\n",
    "\n",
    "try:\n",
    "    from mlxtend.preprocessing import TransactionEncoder\n",
    "    from mlxtend.frequent_patterns import apriori, association_rules\n",
    "    \n",
    "    # 数据转换\n",
    "    TE = TransactionEncoder()\n",
    "    data = TE.fit_transform(symptoms)\n",
    "    df_bool = pd.DataFrame(data, columns=TE.columns_)\n",
    "    \n",
    "    print(f\"转换后的数据形状: {df_bool.shape}\")\n",
    "    print(\"前5行转换数据:\")\n",
    "    print(df_bool.head().T)  # 转置以便更好查看\n",
    "    \n",
    "    # 挖掘频繁项集 - 使用更稳定的方法\n",
    "    print(\"\\n挖掘频繁项集...\")\n",
    "    min_support_values = [0.05, 0.1, 0.15]\n",
    "    mlxtend_results = {}\n",
    "    \n",
    "    for min_support in min_support_values:\n",
    "        print(f\"\\n支持度: {min_support}\")\n",
    "        \n",
    "        try:\n",
    "            # 挖掘频繁项集\n",
    "            frequent_itemsets = apriori(df_bool, min_support=min_support, use_colnames=True)\n",
    "            print(f\"  频繁项集数量: {len(frequent_itemsets)}\")\n",
    "            \n",
    "            if len(frequent_itemsets) == 0:\n",
    "                print(\"  未找到频繁项集，跳过...\")\n",
    "                continue\n",
    "                \n",
    "            # 添加项集长度列\n",
    "            frequent_itemsets['length'] = frequent_itemsets['itemsets'].apply(lambda x: len(x))\n",
    "            \n",
    "            # 显示不同长度的项集数量\n",
    "            length_counts = frequent_itemsets['length'].value_counts().sort_index()\n",
    "            print(\"  项集长度分布:\")\n",
    "            for length, count in length_counts.items():\n",
    "                print(f\"    长度{length}: {count}个\")\n",
    "            \n",
    "            # 只保留包含2个及以上项目的频繁项集用于关联规则\n",
    "            multi_item_sets = frequent_itemsets[frequent_itemsets['length'] >= 2]\n",
    "            print(f\"  多项目频繁项集数量: {len(multi_item_sets)}\")\n",
    "            \n",
    "            if len(multi_item_sets) > 0:\n",
    "                # 生成关联规则 - 使用更安全的方法\n",
    "                try:\n",
    "                    rules = association_rules(multi_item_sets, metric=\"confidence\", min_threshold=0.6)\n",
    "                    mlxtend_results[min_support] = {\n",
    "                        'frequent_itemsets': frequent_itemsets,\n",
    "                        'rules': rules\n",
    "                    }\n",
    "                    \n",
    "                    print(f\"  关联规则数量: {len(rules)}\")\n",
    "                    \n",
    "                    if len(rules) > 0:\n",
    "                        # 显示前3条规则\n",
    "                        print(\"  前3条关联规则:\")\n",
    "                        for i, rule in rules.head(3).iterrows():\n",
    "                            antecedents = ', '.join(list(rule['antecedents']))\n",
    "                            consequents = ', '.join(list(rule['consequents']))\n",
    "                            print(f\"    {antecedents} → {consequents}\")\n",
    "                            print(f\"      支持度: {rule['support']:.3f}, 置信度: {rule['confidence']:.3f}, 提升度: {rule['lift']:.3f}\")\n",
    "                            \n",
    "                except Exception as e:\n",
    "                    print(f\"  生成关联规则时出错: {e}\")\n",
    "                    # 使用备选方法\n",
    "                    print(\"  使用备选方法生成关联规则...\")\n",
    "                    try:\n",
    "                        # 重新计算频繁项集，确保包含所有必要信息\n",
    "                        frequent_itemsets_alt = apriori(df_bool, min_support=min_support, use_colnames=True)\n",
    "                        if len(frequent_itemsets_alt) > 0:\n",
    "                            rules_alt = association_rules(frequent_itemsets_alt, metric=\"confidence\", min_threshold=0.6)\n",
    "                            # 过滤出多项目的规则\n",
    "                            multi_item_rules = rules_alt[\n",
    "                                rules_alt['antecedents'].apply(len) >= 1 & \n",
    "                                rules_alt['consequents'].apply(len) >= 1\n",
    "                            ]\n",
    "                            mlxtend_results[min_support] = {\n",
    "                                'frequent_itemsets': frequent_itemsets_alt,\n",
    "                                'rules': multi_item_rules\n",
    "                            }\n",
    "                            print(f\"  备选方法发现的关联规则数量: {len(multi_item_rules)}\")\n",
    "                    except Exception as e2:\n",
    "                        print(f\"  备选方法也失败: {e2}\")\n",
    "                        \n",
    "        except Exception as e:\n",
    "            print(f\"  挖掘频繁项集时出错: {e}\")\n",
    "            continue\n",
    "\n",
    "except ImportError:\n",
    "    print(\"mlxtend库未安装\")\n",
    "    print(\"请安装: pip install mlxtend\")\n",
    "\n",
    "# 4.使用apyori库作为备选方案\n",
    "print(\"\\n\" + \"=\"*60)\n",
    "print(\"关联规则分析 - apyori库（备选方案）\")\n",
    "print(\"=\"*60)\n",
    "\n",
    "try:\n",
    "    from apyori import apriori\n",
    "    \n",
    "    print(\"使用apyori库进行关联规则分析...\")\n",
    "    \n",
    "    # 使用apyori分析\n",
    "    rules_apyori = apriori(symptoms, min_support=0.1, min_confidence=0.7, min_lift=1.0)\n",
    "    results_apyori = list(rules_apyori)\n",
    "    \n",
    "    print(f\"apyori发现的关联规则数量: {len(results_apyori)}\")\n",
    "    \n",
    "    if len(results_apyori) > 0:\n",
    "        print(\"\\n前10条关联规则:\")\n",
    "        rule_count = 0\n",
    "        for i in results_apyori:\n",
    "            for j in i.ordered_statistics:\n",
    "                X = j.items_base\n",
    "                Y = j.items_add\n",
    "                if len(X) > 0 and len(Y) > 0:  # 确保前后件都不为空\n",
    "                    x = ', '.join([item for item in X])\n",
    "                    y = ', '.join([item for item in Y])\n",
    "                    print(f\"  {x} → {y}\")\n",
    "                    print(f\"    支持度: {i.support:.3f}, 置信度: {j.confidence:.3f}, 提升度: {j.lift:.3f}\")\n",
    "                    rule_count += 1\n",
    "                    if rule_count >= 10:\n",
    "                        break\n",
    "            if rule_count >= 10:\n",
    "                break\n",
    "\n",
    "except ImportError:\n",
    "    print(\"apyori库未安装\")\n",
    "    print(\"请安装: pip install apyori\")\n",
    "\n",
    "# 5.手动实现简单的关联规则分析\n",
    "print(\"\\n\" + \"=\"*60)\n",
    "print(\"简单关联分析 - 手动实现\")\n",
    "print(\"=\"*60)\n",
    "\n",
    "def simple_association_analysis(symptoms_list, min_support=0.1):\n",
    "    \"\"\"简单的手动关联分析\"\"\"\n",
    "    from collections import defaultdict\n",
    "    import itertools\n",
    "    \n",
    "    # 计算单个症状的支持度\n",
    "    symptom_support = defaultdict(int)\n",
    "    total_cases = len(symptoms_list)\n",
    "    \n",
    "    for case in symptoms_list:\n",
    "        for symptom in case:\n",
    "            symptom_support[symptom] += 1\n",
    "    \n",
    "    # 计算症状对的支持度\n",
    "    pair_support = defaultdict(int)\n",
    "    for case in symptoms_list:\n",
    "        # 生成所有可能的症状对\n",
    "        pairs = list(itertools.combinations(sorted(case), 2))\n",
    "        for pair in pairs:\n",
    "            pair_support[pair] += 1\n",
    "    \n",
    "    # 过滤满足最小支持度的症状对\n",
    "    valid_pairs = []\n",
    "    for pair, count in pair_support.items():\n",
    "        support = count / total_cases\n",
    "        if support >= min_support:\n",
    "            # 计算置信度\n",
    "            symptom1, symptom2 = pair\n",
    "            confidence1 = count / symptom_support[symptom1]  # symptom1 -> symptom2\n",
    "            confidence2 = count / symptom_support[symptom2]  # symptom2 -> symptom1\n",
    "            \n",
    "            valid_pairs.append({\n",
    "                'pair': pair,\n",
    "                'support': support,\n",
    "                'confidence_1to2': confidence1,\n",
    "                'confidence_2to1': confidence2\n",
    "            })\n",
    "    \n",
    "    return valid_pairs\n",
    "\n",
    "# 执行简单分析\n",
    "print(\"执行简单关联分析...\")\n",
    "simple_rules = simple_association_analysis(symptoms, min_support=0.1)\n",
    "print(f\"发现 {len(simple_rules)} 个有意义的症状对\")\n",
    "\n",
    "if len(simple_rules) > 0:\n",
    "    # 按支持度排序\n",
    "    simple_rules.sort(key=lambda x: x['support'], reverse=True)\n",
    "    \n",
    "    print(\"\\n前10个有意义的症状对:\")\n",
    "    for i, rule in enumerate(simple_rules[:10]):\n",
    "        symptom1, symptom2 = rule['pair']\n",
    "        print(f\"  {i+1}. {symptom1} & {symptom2}\")\n",
    "        print(f\"     支持度: {rule['support']:.3f}\")\n",
    "        print(f\"     {symptom1} → {symptom2}: {rule['confidence_1to2']:.3f}\")\n",
    "        print(f\"     {symptom2} → {symptom1}: {rule['confidence_2to1']:.3f}\")\n",
    "\n",
    "# 6.症状频率可视化\n",
    "print(\"\\n\" + \"=\"*60)\n",
    "print(\"症状频率可视化\")\n",
    "print(\"=\"*60)\n",
    "\n",
    "# 绘制症状频率图\n",
    "plt.figure(figsize=(12, 8))\n",
    "top_symptoms = symptom_counts.most_common(15)\n",
    "symptoms_names, symptoms_counts = zip(*top_symptoms)\n",
    "\n",
    "plt.barh(range(len(symptoms_names)), symptoms_counts, color='lightblue', alpha=0.7)\n",
    "plt.yticks(range(len(symptoms_names)), symptoms_names)\n",
    "plt.xlabel('出现次数')\n",
    "plt.title('最常见的前15个症状', fontsize=14, fontweight='bold')\n",
    "plt.grid(True, alpha=0.3, axis='x')\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# 7.关联规则总结\n",
    "print(\"\\n\" + \"=\"*60)\n",
    "print(\"关联规则分析总结\")\n",
    "print(\"=\"*60)\n",
    "\n",
    "# 检查mlxtend结果\n",
    "if 'mlxtend_results' in locals() and mlxtend_results:\n",
    "    best_support = max(mlxtend_results.keys())\n",
    "    best_result = mlxtend_results[best_support]\n",
    "    \n",
    "    if 'rules' in best_result and len(best_result['rules']) > 0:\n",
    "        rules_df = best_result['rules']\n",
    "        \n",
    "        # 筛选高质量的规则\n",
    "        high_quality_rules = rules_df[\n",
    "            (rules_df['lift'] > 1.2) & \n",
    "            (rules_df['confidence'] > 0.7)\n",
    "        ]\n",
    "        \n",
    "        print(f\"高质量关联规则数量: {len(high_quality_rules)}\")\n",
    "        \n",
    "        if len(high_quality_rules) > 0:\n",
    "            print(\"\\n最有价值的关联规则 (按提升度排序):\")\n",
    "            high_quality_rules = high_quality_rules.sort_values('lift', ascending=False)\n",
    "            \n",
    "            for i, rule in high_quality_rules.head(10).iterrows():\n",
    "                antecedents = ' + '.join(list(rule['antecedents']))\n",
    "                consequents = ' + '.join(list(rule['consequents']))\n",
    "                \n",
    "                print(f\"\\n规则 {i+1}:\")\n",
    "                print(f\"  如果患者有: {antecedents}\")\n",
    "                print(f\"  那么很可能也有: {consequents}\")\n",
    "                print(f\"  支持度: {rule['support']:.3f}\")\n",
    "                print(f\"  置信度: {rule['confidence']:.3f}\")\n",
    "                print(f\"  提升度: {rule['lift']:.3f}\")\n",
    "\n",
    "# 8.业务建议\n",
    "print(\"\\n\" + \"=\"*60)\n",
    "print(\"业务建议\")\n",
    "print(\"=\"*60)\n",
    "\n",
    "print(\"\"\"\n",
    "💡 中医症状关联分析业务建议:\n",
    "\n",
    "1. **辨证参考**: 强关联的症状组合可为中医辨证提供参考\n",
    "2. **处方辅助**: 关联规则可辅助制定更精准的方剂\n",
    "3. **预防建议**: 识别症状关联有助于疾病预防和早期干预\n",
    "4. **临床验证**: 发现的关联需要在临床实践中进一步验证\n",
    "\n",
    "📊 分析方法建议:\n",
    "- 结合中医理论解释症状关联\n",
    "- 考虑患者体质、年龄等因素\n",
    "- 使用多种支持度阈值进行探索\n",
    "- 重点关注提升度 > 1.5 的强关联\n",
    "\"\"\")\n",
    "\n",
    "print(\"\\n关联规则分析完成!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0bf7ef3e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3f835f1f",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
